home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / unix / uucp103d / part08 < prev    next >
Encoding:
Internet Message Format  |  1990-02-04  |  48.8 KB

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i052: uucp 1.03D - unix compatible uucp/mail/news system, Part08/16
  5. Message-ID: <11291@xanth.cs.odu.edu>
  6. Date: 4 Feb 90 02:36:14 GMT
  7. Sender: tadguy@cs.odu.edu
  8. Reply-To: overload!dillon (Matt Dillon)
  9. Lines: 1948
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11. X-Mail-Submissions-To: Amiga@cs.odu.edu
  12.  
  13. Submitted-by: overload!dillon (Matt Dillon)
  14. Posting-number: Volume 90, Issue 052
  15. Archive-name: unix/uucp-1.03d/part08
  16.  
  17. #!/bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 8 (of 16)."
  24. # Contents:  SlowSetup.DOC src/dmail/load_mail.c src/uucico/gio.c
  25. # Wrapped by tadguy@xanth on Sat Feb  3 20:51:14 1990
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'SlowSetup.DOC' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'SlowSetup.DOC'\"
  29. else
  30. echo shar: Extracting \"'SlowSetup.DOC'\" \(14853 characters\)
  31. sed "s/^X//" >'SlowSetup.DOC' <<'END_OF_FILE'
  32. X
  33. X                SLOWSETUP.DOC
  34. X
  35. X                Matthew Dillon
  36. X                891 Regal Rd.
  37. X                Berkeley, Ca. 94708
  38. X
  39. X                pacbell.PacBell.COM!sorinc!overload!dillon
  40. X
  41. X
  42. X            GETTING UUCP UP AND RUNNING FOR REAL
  43. X
  44. X
  45. X    This UUCP distribution in general is not for the uninitiated.  That is,
  46. X    it is not user friendly.  This particular document outlines a general
  47. X    installation procedure.  Be warned that there are a LOT of things you
  48. X    will have to do to bring up UUCP on your machine.
  49. X
  50. X    This document shows a TYPICAL setup.  You will most likely want to
  51. X    modify the example to fit your own needs.  I cover all the points
  52. X    though.
  53. X
  54. X    (1) You made backups of the distribution floppies, right?  DO NOT
  55. X    MODIFY THE DISTRIBUTION FLOPPIES.  The instructions below are
  56. X    long and some are complex and you may wish to refer to the
  57. X    original distribution diskettes if you accidently mess something
  58. X    up.
  59. X
  60. X
  61. X    (2A) Installing UUCP on a single floppy system.
  62. X
  63. X    Well, it *is* possible, but difficult.    you need to make as much
  64. X    space as possible available on the main floppy.
  65. X
  66. X    The second distribution disk contains only the source and manual
  67. X    pages.    I suggest you shuffle things around a bit.  You already
  68. X    have a copy of the first distribution diskette. I suggest you
  69. X    format a new disk and put the MAN directory of the second
  70. X    distribution disk on it.  Note that there is a MAN directory
  71. X    on the boot disk as well but this one contains only dmail.help
  72. X    which you need to gain online help from dmail.
  73. X
  74. X    The following executables are required on the boot floppy and
  75. X    should not be moved off.  You should move as many of the remaining
  76. X    executables somewhere else as you can.
  77. X
  78. X        Required Executables in C
  79. X
  80. X        c/dmail
  81. X        c/getty
  82. X        c/rmail
  83. X        c/uucico
  84. X        c/rnews
  85. X        c/uucp
  86. X        c/unbatcher
  87. X        c/dme        (unless you configure your own editor)
  88. X        c/sendmail
  89. X        c/uux
  90. X        c/uuxqt
  91. X
  92. X    You will want to change the ASSIGNments in s/startup-sequence
  93. X    as follows:
  94. X
  95. X        Assign UUSPOOL:    UUCP:SPOOL
  96. X        Assign UUMAIL:    UUCP:MAIL
  97. X        Assign UUNEWS:    UUCP:MAIL/NEWS
  98. X
  99. X    These directories MUST be in nonvoltile storage or your USENET
  100. X    node will be unreliable.
  101. X
  102. X    (2B) Installing UUCP on a duel floppy system.
  103. X
  104. X    In this case very little shuffling is required.  I suggest
  105. X    the second floppy be used for UUSPOOL:, UULIB:, UUMAIL:, UUNEWS:,
  106. X    GETTY:, and UUPUB:.
  107. X
  108. X    Format a new floppy (this will be your second floppy) and create
  109. X    directories as follows:
  110. X
  111. X        MakeDir df1:spool
  112. X        MakeDir df1:mail
  113. X        MakeDir df1:mail/news
  114. X        MakeDir df1:pub
  115. X        MakeDir df1:lib
  116. X
  117. X    Modify the Assignments in s/startup-sequence of the boot floppy
  118. X    as follows:
  119. X
  120. X        Assign UUSPOOL:    df1:spool
  121. X        Assign UULIB:    df1:lib
  122. X        Assign UUMAIL:    df1:mail
  123. X        Assign UUNEWS:    df1:mail/news
  124. X        Assign GETTY:    UULIB:
  125. X        Assign UUPUB:    df1:pub
  126. X
  127. X    Copy df0:lib to df1:lib and either delete or rename df0:lib to
  128. X    prevent confusion.  What we have done is move all dynamic storage
  129. X    to df1: .. files that will change a lot or require a lot of disk
  130. X    space.    Specifically, UULIB: was moved to DF1: because the
  131. X    sequence number file is kept in UULIB: and this is updated for
  132. X    each mail message sent.
  133. X
  134. X    (2B) Installing UUCP on a Hard Drive
  135. X
  136. X    Make a directory called UUCP on your hard drive somewhere.  And
  137. X    Assign UUCP: to it.   Copy the contents of both distribution
  138. X    floppies to your harddrive:
  139. X
  140. X        (put first disk in DF0:)
  141. X        1> Copy df0: UUCP: ALL CLONE
  142. X        (put second disk in DF0:)
  143. X        1> Copy df0: UUCP: ALL CLONE
  144. X
  145. X    It is easiest to keep all the directories in one place.  Note
  146. X    that a MAN directory exists on both distribution floppies, simply
  147. X    merge them together.
  148. X
  149. X    Merge the startup-sequence on the boot floppy into your master
  150. X    startup-sequence.  Make sure you get all the Assigns and that
  151. X    they are properly reassigned to the appropriate directory on
  152. X    the harddisk.  Most people normally make a master UUCP: assign
  153. X    as a reference point to other assigns.
  154. X
  155. X
  156. X    Be sure that UUSPOOL:, UUMAIL:, UUNEWS: and UUPUB: are assigned
  157. X    to your hard disk instead of ram.
  158. X
  159. X    You will most likely want to run DCron and Getty from your
  160. X    startup-sequence.  Be sure that UUCP:C is assigned *before*
  161. X    these programs are run so they pick up the appropriate path.
  162. X
  163. X    If Getty interferes with any terminal program you might use
  164. X    you may be forced to BREAK it.    Remember to restart it to
  165. X    enable incomming UUCP calls again.
  166. X
  167. X    DCron is an extremely useful utility to run, especially in
  168. X    systems with hard disks.  The only thing you have to watch out
  169. X    for is to be sure to BREAK it (kill it) before shutting off your
  170. X    machine.  DCron writes to its log file and runs other programs
  171. X    based on the date and you don't want to accidently turn off your
  172. X    machine when DCron has just started up some other program that
  173. X    may write to your hard disk.
  174. X
  175. X    In the context of UUCP, DCron is normally used to automatically
  176. X    poll systems in the wee hours while you are asleep, to trim
  177. X    log files automagically, and maybe disable the modem's speaker
  178. X    while you are asleep (at least, that is what I use it for).
  179. X
  180. X    Most people with HDs running UUCP leave their Amiga's on 24 hours
  181. X    a day.
  182. X
  183. X                Other System Directories
  184. X
  185. X    Merge the mountlist into your master mountlist and copy any
  186. X    devices from l that you do not already have into your
  187. X    master l directory.
  188. X
  189. X    merge or copy uucp:s/crontab to s:crontab and uucp:s/.edrc to
  190. X    s:.edrc .
  191. X
  192. X    You can ignore files in uucp:system, they are standard system
  193. X    files.
  194. X
  195. X        ----    --  -    -   -    -   -    -  --    ----
  196. X
  197. X    (3)     Other startup-sequence efficiency considerations
  198. X
  199. X    UUCP relies heavily on the Amiga's multitasking capabilities.
  200. X    Most programs execute other programs.  Many programs in UUCP:C
  201. X    may be made resident as shown by the pure bit being set.  You
  202. X    will probably at least want to make C:RUN resident if you haven't
  203. X    already.
  204. X
  205. X    Depending on available RAM you may want to make certain other
  206. X    progams resident.  Here are some suggestions:
  207. X
  208. X        uucp:c/dme        ; run by dmail to edit mail
  209. X        uucp:c/uuxqt        ; run by uucico to handle received files
  210. X        uucp:c/rmail        ; run by uuxqt to handle received mail
  211. X        uucp:c/sendmail     ; run by dmail to handle outgoing mail
  212. X
  213. X        (note that uucp:c/sendmail and uucp:c/rmail are the same
  214. X         executable just renamed)
  215. X
  216. X    STACK:    All programs should run with a stack of 8192.  This
  217. X    has been tested for all programs except RNews and ANews which
  218. X    may require more.
  219. X
  220. X    RNEWS:    RNews currently takes a huge amount of memory and
  221. X    will run only on machines with at least 1.5MB of ram.  Even
  222. X    with 1.5MB you may need to run rnews manually instead of having
  223. X    it automatically run by uuxqt.    In this case rename the rnews
  224. X    executable to something else and create a dummy script file
  225. X    in its place (named as 'rnews') with the script bit set.
  226. X
  227. X    (4)     System requirements
  228. X
  229. X    Be sure you are running at least version 1.3 of the operating
  230. X    system.  The main consideration is that you are using at least
  231. X    the 1.3 serial device.
  232. X
  233. X    The NULL: device is required, this is in the l directory of
  234. X    the boot floppy as already discussed.
  235. X
  236. X    The UUSER: device is not required unless you want to start
  237. X    getting fancy with the Getty.  This is mainly a programmer's
  238. X    tool.
  239. X
  240. X    (5)     Getty
  241. X
  242. X    Normally one runs a Getty in his startup-sequence on the internal
  243. X    serial port (from which you wish to receive calls).  Currently
  244. X    only one Getty may be run PER SERIAL DEVICE NAME, and using other
  245. X    units of a given serial device will interfere with Getty's operation.
  246. X    This is due to the difficulty of implementation in Getty and will
  247. X    eventually be fixed (to fix the problem I have to patch into
  248. X    the OpenDevice and CloseDevice vectors).
  249. X
  250. X    So for now you can really only run Getty on the internal serial
  251. X    device.
  252. X
  253. X    Getty does its best to not interfere with comm programs and
  254. X    the like, but if a comm program refuses to run because it
  255. X    can't get exclusive access to the serial port you may have
  256. X    to kill the Getty by BREAKing it from a CLI.
  257. X
  258. X    Refer to the manual page MAN:Getty for more information (for
  259. X    floppy based systems all manual pages are on the second
  260. X    distribution diskette).
  261. X
  262. X    (6)     SHELL-STARTUP
  263. X
  264. X    Assuming you are using the 1.3 Shell, the S:Shell-Startup file
  265. X    normally contains at least a Path command and Stack command to
  266. X    properly setup a newshell's path and stack.  Be sure the stack is
  267. X    at least 8192 for this distribution of UUCP and add the UUCP:C (or
  268. X    wherever you have placed the distribution executables) to your path
  269. X    list.  Older UUCP distributions required a huge stack, this has
  270. X    been fixed.
  271. X
  272. X    (7)                   SITE-SETUP CONTROL FILES
  273. X
  274. X    The following is a description of control and log files required
  275. X    for UUCP and how you must modify them to install your system.
  276. X
  277. X    (GETTY: is normally Assign'd to UULIB:)
  278. X
  279. X    GETTY:Getty-Header
  280. X
  281. X        This file contains the header line that is printed before a
  282. X        login: prompt and is typically only two or three lines long.
  283. X        The header usually contains your node name and the version of
  284. X        the OS you are running under so people calling from term
  285. X        programs know who you are.
  286. X
  287. X        (Getty can be used to run things other than uucico)
  288. X
  289. X        Modify accordingly.
  290. X
  291. X    GETTY:Passwd
  292. X
  293. X        The password file is used by Getty to authenticate login
  294. X        requests.  In the context of UUCP, remote UUCICOs that call
  295. X        your machine up will provide a login and password.    Getty
  296. X        handles this and if the login is valid and the password matches
  297. X        will run the appropriate program found in the password file.
  298. X
  299. X        Getty also deals with such features as automatic disconnect on
  300. X        timeout and logs times for all incomming and outgoing calls.
  301. X
  302. X        In a serious system you should first remove all the junk
  303. X        entries that come with the distribution.   You need an entry
  304. X        for each remote machine you want to be able to call you.  You
  305. X        do not necessarily need to give them logins that corrospond to
  306. X        their machine names though this is how it is usually done.
  307. X
  308. X        Other programs in the future will be able to be run from
  309. X        a Getty.
  310. X
  311. X        Later versions of UUCP will implement MAILER-DAEMON type
  312. X        stuff like 'unknown user', in which case the password file
  313. X        will be used to define which user names are valid on the
  314. X        system.
  315. X
  316. X    GETTY:LOGFILE
  317. X
  318. X        The logfile is appended to by Getty whenever an incomming
  319. X        call occurs or somebody takes over the serial port.  It
  320. X        logs connect and disconnect times for incomming calls and
  321. X        usage for external programs.
  322. X
  323. X    UULIB:Domain
  324. X
  325. X        In nearly every case you will not need this file.
  326. X
  327. X        Those of you who wish to do domain routing through
  328. X        their machine or have more than one default for
  329. X        unknown destinations should refer to the manual
  330. X        page MAN:Domains.
  331. X
  332. X    UULIB:.Signature
  333. X
  334. X        .Signature is used by the Mail program and normally appended
  335. X        to outgoing mail.
  336. X
  337. X        Modify accordingly.
  338. X
  339. X    UULIB:Seq
  340. X
  341. X        The Seq file should exist but otherwise not be modified by
  342. X        the user (except for setting it to a "1" once a year).  This
  343. X        file is atomically updated and used to provide unique filenames
  344. X        and mail IDs for outgoing mail.
  345. X
  346. X    UULIB:Security
  347. X
  348. X        This file contains a list of allowed directories remote UUCP
  349. X        transfers may read and write to.  Refer to the Security manual
  350. X        page.  This file never contains the UUSPOOL: directory which
  351. X        is implicitly read-write.
  352. X
  353. X        You need not modify this file now but should keep it in mind.
  354. X        It protects your system in as much as I have been able to
  355. X        close the loopholes.  Loopholes might still exist.
  356. X
  357. X    UULIB:news.distribution
  358. X
  359. X        This file contains a list of news distribution idents for
  360. X        various areas and must normally be modified according to
  361. X        where you are.. you need to be a UUCP guru to do this.  Most
  362. X        people can just leave it alone.
  363. X
  364. X    UULIB:Config
  365. X
  366. X        This file contains configuration information for many
  367. X        executables in UUCP:C and should be modified accordingly.
  368. X
  369. X        Be sure you modify at least the following entries.    REFER TO
  370. X        THE 'Assigns' MANUAL PAGE.
  371. X
  372. X        NodeName
  373. X        UserName
  374. X        RealName
  375. X        NewsFeed    (not required if you don't care about news)
  376. X        Organization
  377. X        TimeZone
  378. X        DefaultNode
  379. X
  380. X        **** Take some time to pick a node name for yourself.  It
  381. X         should be no more than 8 characters long.  Some UUCP sites
  382. X         barf at node names longer than 6 chars so if you are not
  383. X         sure of your neighbors pick one no more than 6 characters
  384. X         long.    Your site name should be in lower case.
  385. X
  386. X    UULIB:L.Sys
  387. X
  388. X        This file contains site information for sites that may call
  389. X        you up or you may call up.
  390. X
  391. X        You must modify this file appropriately before you can run UUCP,
  392. X        refer to the 'L.Sys' manual page.
  393. X
  394. X    UULIB:Aliases
  395. X
  396. X        This is a mail aliases file with aproximately the same
  397. X        power as /usr/lib/aliases on UNIX systems.    You should
  398. X        refer to the 'Aliases' manual page and modify this file as
  399. X        appropriate for various defaults like 'postmaster'... to
  400. X        whatever user name you pick for yourself.
  401. X
  402. X    UUCP:S/Crontab
  403. X
  404. X        This is a functional Crontab file for use with the DCron program.
  405. X        This file is normally moved to S: (it is useless in UUCP:S).
  406. X
  407. X    UUSPOOL:LOGFILE
  408. X
  409. X        UUCICO and other programs log errors and other things to
  410. X        this file.    Normally you use DCron to clean up this and
  411. X        other log files once daily to keep them from getting to large.
  412. X
  413. X
  414. X    (8)     TESTING / DMAIL
  415. X
  416. X    You will next want to test your UUCP configuration.  If testing
  417. X    with a friend's Amiga running the same distribution simply
  418. X    email to him, then one of you run uucico -s<remotesystem>
  419. X    just like in QuickSetup.DOC, except this time you are using
  420. X    the system name he picked instead of 'test1' or 'test2'.
  421. X
  422. X    If the initial tests in QuickSetup.DOC worked and the system
  423. X    is not working now check the following (common problems):
  424. X
  425. X        (a) the login and password in your L.Sys file (that uucico uses
  426. X        to login to the remote machine) matches the login and
  427. X        password in the remote machine's Getty:Passwd file.
  428. X
  429. X        (b) There is an entry for your node in the remote machine's
  430. X        L.Sys file and vise versa
  431. X
  432. X        (c) The telephone number is correct
  433. X
  434. X        (d) the node names are all in lower case
  435. X
  436. X        (e) you constructed the email address correctly (nodename!user)
  437. X
  438. X    I suggest you get UUCP running with a friend before getting it
  439. X    running with a UNIX system as it is easier to test it with a
  440. X    friend.
  441. X
  442. X    Assuming you email to the user name he picked for his UULIB:Config
  443. X    'UserName' entry and he did the same thing to you, entering
  444. X    'dmail' without any arguments will bring up the mail shell
  445. X    and allow you to read the message after transfer via UUCico
  446. X    is complete.  You can check that the email actually arrived
  447. X    into the right mail box in UUMAIL: by simply getting a directory
  448. X    of UUMAIL:
  449. X
  450. X    READ the manual page for DMail for information on the
  451. X    construction of mail paths to other systems and users.
  452. X
  453. X
  454. END_OF_FILE
  455. if test 14853 -ne `wc -c <'SlowSetup.DOC'`; then
  456.     echo shar: \"'SlowSetup.DOC'\" unpacked with wrong size!
  457. fi
  458. # end of 'SlowSetup.DOC'
  459. fi
  460. if test -f 'src/dmail/load_mail.c' -a "${1}" != "-c" ; then 
  461.   echo shar: Will not clobber existing file \"'src/dmail/load_mail.c'\"
  462. else
  463. echo shar: Extracting \"'src/dmail/load_mail.c'\" \(13593 characters\)
  464. sed "s/^X//" >'src/dmail/load_mail.c' <<'END_OF_FILE'
  465. X
  466. X/*
  467. X *  LOAD_MAIL.C
  468. X *
  469. X *  (C) Copyright 1985-1990 by Matthew Dillon,  All Rights Reserved.
  470. X *
  471. X *  file-io routines to scan the mail file and load required information.
  472. X *
  473. X *
  474. X *  Global Routines:    HOLD_LOAD()         hold on loading mail after change
  475. X *            NOHOLD_LOAD()       hold off.. load if changes
  476. X *            LOAD_CHANGES()      reload mail if changed
  477. X *            LOAD_MAIL()         load/reload mail
  478. X *            SAVE_FILE()         save mail items back to spool
  479. X *            CHECK_NEW_MAIL()    check for new mail
  480. X *            WRITE_FILE()        append mail items to a file
  481. X *            GET_EXTRA_OVR()     ret index of Field (create if not)
  482. X *            ADD_EXTRA()         add another field (reloads mail)
  483. X *            DELETE_EXTRA()      delete a field
  484. X *            GET_EXTRA()         ret index of Field, or error
  485. X *            M_SELECT()          select on current message list
  486. X *
  487. X *
  488. X *  Static Routines:    LOAD_HASH()         load hash table from fields list
  489. X *            FREE_ENTRY()        unload EVERYTHING
  490. X *            FREE_TABLE()        unload all Fields table
  491. X *            LOAD_FILE()         raw file loading/counting
  492. X *
  493. X *
  494. X */
  495. X
  496. X#include <stdio.h>
  497. X#include <sys/file.h>
  498. X#include "dmail.h"
  499. X
  500. Xvoid do_flock();
  501. Xvoid free_table();
  502. Xvoid load_hash();
  503. X
  504. X#define NOHOLD    0
  505. X#define HOLD    1
  506. X
  507. X#define NO_BASE     0
  508. X#define NO_FIELDS   1
  509. X#define ENTRY_OK    2
  510. X
  511. Xstruct FIND Find[MAXTYPE + 1] = {
  512. X    "From:"   , 5, 1, 0,
  513. X    "To:"     , 3, 1, 0,
  514. X    "Subject:", 8, 1, 0 };
  515. X
  516. Xstatic int  File_size;
  517. Xstatic int  changed, load_hold;
  518. Xstatic int  Hash[256];
  519. X
  520. Xstatic char *quo_quo = "";
  521. X
  522. Xvoid
  523. Xhold_load()
  524. X{
  525. X    load_hold = 1;
  526. X}
  527. X
  528. Xvoid
  529. Xnohold_load()
  530. X{
  531. X    void load_changes();
  532. X    load_hold = 0;
  533. X    load_changes();
  534. X}
  535. X
  536. Xvoid
  537. Xload_changes()
  538. X{
  539. X    if (changed  &&  !load_hold)
  540. X    load_mail(Entries, 1);
  541. X}
  542. X
  543. Xinitial_load_mail()
  544. X{
  545. X    if (load_mail (0, 0) < 0)
  546. X    return (-1);
  547. X    return ((Entries) ? 1 : -1);
  548. X}
  549. X
  550. X
  551. Xstatic
  552. Xload_mail(at, from0)
  553. X{
  554. X    FILE *fi;
  555. X    int i, count, file_size;
  556. X
  557. X    if (No_load_mail)
  558. X    return (-1);
  559. X    push_break();
  560. X    load_hash();
  561. X    if (from0)
  562. X    free_table (0, HOLD);
  563. X    else
  564. X    free_table (at, NOHOLD);
  565. X    fi = fopen (mail_file, "r+");
  566. X    if (m_fi != NULL)
  567. X    fclose (m_fi);
  568. X    m_fi = fopen (mail_file, "r+");
  569. X    if (fi == NULL  ||  m_fi == NULL) {
  570. X    pop_break();
  571. X    return (-1);
  572. X    }
  573. X    do_flock (fileno(m_fi), LOCK_EX);
  574. X    if (at)
  575. X    fseek (fi, Entry[at].fpos, 0);
  576. X    else
  577. X    fseek (fi, 0, 0);
  578. X    count = Entries;
  579. X    while (search_from(fi))
  580. X    ++count;
  581. X    if (Entries != count) {
  582. X    if (!lmessage_overide)
  583. X        printf ("%d Other Items loaded\n", count - Entries);
  584. X    lmessage_overide = 0;
  585. X    Entry = (struct ENTRY *)realloc (Entry, sizeof(*Entry) * (count + 1));
  586. X    bzero (&Entry[Entries], sizeof(*Entry) * (count + 1 - Entries));
  587. X    }
  588. X    Entries = count;
  589. X    for (i = at; i < Entries; ++i)
  590. X    Entry[i].no  =    Entry[i].status = 0;
  591. X    Entry[i].fpos = File_size = file_size = ftell (fi);
  592. X    fclose (fi);
  593. X    load_file ((from0) ? 0 : at);
  594. X    if (file_size != File_size) {       /* Last entry incomplete?       */
  595. X    free_table (Entries - 1, NOHOLD);
  596. X    }
  597. X    changed = 0;
  598. X    flock (fileno(m_fi), LOCK_UN);
  599. X    pop_break();
  600. X    return (1);
  601. X}
  602. X
  603. Xvoid
  604. Xdo_flock(fd, stat)
  605. X{
  606. X    if (flock(fd, stat | LOCK_NB) < 0) {
  607. X    puts ("File in use, Waiting for lock");
  608. X    flock (fd, stat);
  609. X    puts ("Have lock");
  610. X    }
  611. X}
  612. X
  613. Xstatic
  614. Xload_file(at)
  615. Xint at;
  616. X{
  617. X    FILE *fi;
  618. X    char *next, *ptr;
  619. X    int i, bit, maxbit, len, count, havefrom;
  620. X
  621. X    maxbit = 0;
  622. X    for (i = 0; Find[i].search != NULL; ++i)
  623. X    maxbit = (maxbit << 1) | 1;
  624. X    fi = fopen (mail_file, "r");
  625. X    count = -1;
  626. X    havefrom = 0;
  627. X    while (havefrom  ||  search_from (fi)) {
  628. X    havefrom = 0;
  629. X    if (++count >= Entries)
  630. X        break;
  631. X    len = strlen(Buf) - 1;
  632. X    Buf[len] = '\0';
  633. X    next = next_word(Buf);
  634. X    len -= next - Buf;
  635. X    Entry[count].fpos = ftell (fi);
  636. X    Entry[count].from = malloc (len + 1);
  637. X    bcopy (next, Entry[count].from, len + 1);
  638. X
  639. X    /* SEARCH FIELD LIST */
  640. X
  641. X    bit = 0;
  642. X    if (XDebug)
  643. X        printf ("No %d  ---------------------\n", count + 1);
  644. X    while (fgets (Buf, MAXFIELDSIZE, fi) != NULL) {
  645. X        if (Buf[0] == '\n')
  646. X        break;
  647. X        if (isfrom(Buf)) {
  648. X        havefrom = 1;
  649. X        break;
  650. X        }
  651. X        len = strlen(Buf) - 1;
  652. X        Buf[len] = '\0';
  653. X        if (XDebug)
  654. X        printf ("CHECK: %s\n", Buf);
  655. X        next = next_word(Buf);
  656. X        len -= next - Buf;
  657. X        if (Hash[*Buf] == 0)
  658. X        continue;
  659. X        if (Hash[*Buf] > 0) {
  660. X        i = Hash[*Buf] & 0xff;
  661. X        if (strncmp (Find[i].search, Buf, Find[i].len) == 0)
  662. X            goto found;
  663. X        continue;
  664. X        }
  665. X        for (i = -Hash[*Buf] & 0xff; Find[i].search; ++i) {
  666. X        if (*Find[i].search != *Buf)
  667. X            break;
  668. X        if (strncmp (Find[i].search, Buf, Find[i].len) == 0)
  669. X            goto found;
  670. X        }
  671. X        continue;
  672. Xfound:
  673. X        if (XDebug)
  674. X        printf ("Found: %d %s\n", i, Buf);
  675. X        if (Find[i].notnew == 0) {
  676. X        Find[i].notnew = 1;
  677. X        ptr = Buf;
  678. X        while (*ptr  &&  *ptr != ':')
  679. X            ++ptr;
  680. X        ++ptr;
  681. X        Find[i].search =
  682. X            realloc (Find[i].search, ptr - Buf + 1);
  683. X        strncpy (Find[i].search, Buf, ptr - Buf);
  684. X        *(Find[i].search + (ptr - Buf)) = '\0';
  685. X        Find[i].len = strlen(Find[i].search);
  686. X        }
  687. X        compile_field (Buf, fi);
  688. X        Entry[count].fields[i] =
  689. X            malloc (strlen(next) + 1);
  690. X        strcpy (Entry[count].fields[i], next);
  691. X        if ((bit |= (1 << i)) == maxbit)
  692. X        break;
  693. X    }
  694. X    if (bit != maxbit) {
  695. X        for (i = 0; Find[i].search != NULL; ++i) {
  696. X        if (((1 << i) & bit) == 0) {
  697. X            Entry[count].fields[i] = quo_quo;
  698. X        }
  699. X        }
  700. X    }
  701. X    }
  702. X    File_size = ftell (fi);
  703. X    fclose (fi);
  704. X    return (1);
  705. X}
  706. X
  707. X
  708. Xstatic void
  709. Xload_hash()
  710. X{
  711. X    register int i, c;
  712. X
  713. X    bzero (Hash, sizeof(Hash));
  714. X    for (i = 0; Find[i].search; ++i) {
  715. X    c = *Find[i].search;
  716. X    if (Hash[c] > 0)
  717. X        Hash[c] = -Hash[c];
  718. X    if (Hash[c] == 0)
  719. X        Hash[c] = i | 0x100;
  720. X    }
  721. X}
  722. X
  723. X
  724. Xvoid
  725. Xfree_entry()
  726. X{
  727. X    free_table(0, NOHOLD);
  728. X    Entry = (struct ENTRY *)realloc (Entry, sizeof(*Entry));
  729. X    bzero (Entry[0].fields, sizeof(Entry[0].fields));
  730. X    File_size = Entries = 0;
  731. X    Entry->status = Entry->no = Entry->fpos = Current = 0;
  732. X    Listsize = 3;
  733. X    if (m_fi) {
  734. X    fclose (m_fi);
  735. X    m_fi = NULL;
  736. X    }
  737. X}
  738. X
  739. X
  740. Xstatic void
  741. Xfree_table(at, hold)
  742. X{
  743. X    int i, j;
  744. X
  745. X    for (i = at; i < Entries; ++i) {
  746. X    xfree (Entry[i].from);
  747. X    for (j = 0; Find[j].search != NULL; ++j) {
  748. X        if (Entry[i].fields[j] != quo_quo)
  749. X        xfree (Entry[i].fields[j]);
  750. X    }
  751. X    }
  752. X    Entries = (hold == HOLD) ? Entries : at;
  753. X    File_size = (at) ? Entry[Entries].fpos : 0;
  754. X}
  755. X
  756. Xstatic
  757. Xsearch_from(fi)
  758. XFILE *fi;
  759. X{
  760. X    while (fgets (Buf, MAXFIELDSIZE, fi) != NULL) {
  761. X    if (isfrom (Buf))
  762. X        return (1);
  763. X    }
  764. X    return (0);
  765. X}
  766. X
  767. X
  768. Xsave_file(reload, mark, notmark)
  769. X{
  770. X    FILE *fiscr;
  771. X    int fdscr;
  772. X    int new_size, i, count;
  773. X    char scratch[64];
  774. X
  775. X    for (i = 0; i < Entries; ++i) {
  776. X    if ((Entry[i].status & mark) != mark  ||
  777. X        (~Entry[i].status & notmark) != notmark)
  778. X        break;
  779. X    }
  780. X    if (i == Entries) {
  781. X    m_select (Nulav, M_RESET);
  782. X    puts ("No Changes Made");
  783. X    return (Entries);
  784. X    }
  785. X    if (m_fi == NULL)
  786. X    return (-1);
  787. X    count = 0;
  788. X    sprintf (scratch, "tmp:dmail%d", getpid());
  789. X    do_flock (fileno(m_fi), LOCK_EX);
  790. X    fdscr = open (scratch, O_RDWR | O_CREAT | O_TRUNC, MAILMODE);
  791. X#ifdef AMIGA        /*    fix bug in Lattice C fdopen */
  792. X    fiscr = fopen("nil:", "w");
  793. X    fclose(fiscr);
  794. X#endif
  795. X    fiscr = fdopen (fdscr, "a+");
  796. X    for (i = 0; i < Entries; ++i) {
  797. X    if ((Entry[i].status & mark) == mark  &&
  798. X        (~Entry[i].status & notmark) == notmark) {
  799. X        ++count;
  800. X        fputs ("From ", fiscr);
  801. X        fputs (Entry[i].from, fiscr);
  802. X        putc ('\n', fiscr);
  803. X        fseek (m_fi, Entry[i].fpos, 0);
  804. X        while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) {
  805. X        if (isfrom(Buf))
  806. X            break;
  807. X        fputs (Buf, fiscr);
  808. X        }
  809. X    }
  810. X    }
  811. X
  812. X    /* If NEW MAIL has come in, append that to the scratch file also */
  813. X
  814. X    new_size = (fseek (m_fi, 0, 2) >= 0) ? ftell(m_fi) : File_size;
  815. X    if (File_size != new_size) {
  816. X    fseek (m_fi, File_size, 0);
  817. X    while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL)
  818. X        fputs (Buf, fiscr);
  819. X    }
  820. X
  821. X    /* Write scratch file back to mail file, or try to */
  822. X
  823. X    fflush (fiscr);
  824. X    fflush (m_fi);
  825. X
  826. X    lseek (fdscr, 0 ,0);
  827. X#ifdef UNIX
  828. X    lseek (fileno(m_fi), 0, 0);
  829. X    while ((i = read (fdscr, Buf, MAXFIELDSIZE)) > 0)
  830. X    write (fileno(m_fi), Buf, i);
  831. X    ftruncate (fileno(m_fi), lseek (fileno(m_fi), 0, 1));
  832. X#else
  833. X    fclose(m_fi);
  834. X    if (m_fi = fopen (mail_file, "w")) {
  835. X    while ((i = read (fdscr, Buf, MAXFIELDSIZE)) > 0)
  836. X        write (fileno(m_fi), Buf, i);
  837. X    fclose(m_fi);
  838. X    m_fi = fopen (mail_file, "r+");
  839. X    }
  840. X    if (m_fi == NULL) {
  841. X    printf("Unable to re-open %s !\n", mail_file);
  842. X    return(-1);
  843. X    }
  844. X#endif
  845. X    if (lseek (fileno(m_fi), 0, 2) == 0  &&  !reload) {
  846. X    if (Did_cd == 0) {
  847. X        fclose(m_fi);
  848. X        m_fi = NULL;
  849. X        if (unlink (mail_file) == 0)
  850. X        printf ("%s  Removed\n", mail_file);
  851. X        else
  852. X        printf ("0 messages left in %s\n", mail_file);
  853. X    }
  854. X    }
  855. X    fclose (fiscr);
  856. X    if (m_fi)
  857. X    fclose (m_fi);          /* Effectively unlocks the descriptor */
  858. X    m_fi = NULL;
  859. X    unlink (scratch);
  860. X    if (reload) {
  861. X    free_entry();
  862. X    load_mail(0, 0);
  863. X    }
  864. X    m_select (Nulav, M_RESET);
  865. X    return (count);
  866. X}
  867. X
  868. Xvoid
  869. Xcheck_new_mail()
  870. X{
  871. X    push_break();
  872. X    if (m_fi == NULL) {
  873. X    m_fi = fopen (mail_file, "r+");
  874. X    if (m_fi == NULL) {
  875. X        pop_break();
  876. X        return;
  877. X    }
  878. X    }
  879. X    if (fseek (m_fi, 0, 2) < 0 || ftell(m_fi) != File_size)
  880. X    load_mail(Entries, 1);
  881. X    pop_break();
  882. X}
  883. X
  884. X
  885. Xwrite_file(file, modes, mark, notmark)
  886. Xchar *file;
  887. X{
  888. X    int i, fd = 1, notopen = 1;
  889. X    FILE *fi = NULL;
  890. X
  891. X    for (i = 0; i < Entries; ++i) {
  892. X    if ((Entry[i].status & mark) == mark  &&
  893. X        (~Entry[i].status & notmark) == notmark) {
  894. X        if (notopen) {
  895. X        notopen = 0;
  896. X        fd = open (file, O_APPEND | O_WRONLY | modes, MAILMODE);
  897. X        if (fd < 0)
  898. X            return (-1);
  899. X        do_flock (fd, LOCK_EX);
  900. X#ifdef AMIGA        /*    fix bug in Lattice C fdopen */
  901. X        fi = fopen("nil:", "w");
  902. X        fclose(fi);
  903. X#endif
  904. X        fi = fdopen (fd, "a");
  905. X
  906. X#ifdef NOTDEF
  907. X        if (fi) {
  908. X            printf("ptr     %08lx\n", fi->_ptr);
  909. X            printf("rcnt    %08lx\n", fi->_rcnt);
  910. X            printf("wcnt    %08lx\n", fi->_wcnt);
  911. X            printf("base    %08lx\n", fi->_base);
  912. X            printf("size    %08lx\n", fi->_size);
  913. X            printf("flag    %08lx\n", fi->_flag);
  914. X            printf("file    %08lx\n", fi->_file);
  915. X            return(-1);
  916. X        }
  917. X#endif
  918. X        }
  919. X        fputs ("From ", fi);
  920. X        fputs (Entry[i].from, fi);
  921. X        putc ('\n', fi);
  922. X        if (m_fi) {
  923. X        fseek (m_fi, Entry[i].fpos, 0);
  924. X        while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) {
  925. X            if (isfrom(Buf))
  926. X            break;
  927. X            fputs (Buf, fi);
  928. X        }
  929. X        }
  930. X    }
  931. X    }
  932. X    if (!notopen)
  933. X    fclose (fi);
  934. X    return (1);
  935. X}
  936. X
  937. X/*
  938. X * Basic scheme: Each entry has a fields list.    Each entry in the fields list
  939. X * is guarenteed to be a valid malloc'd pointer (except some may be set to
  940. X * quo_quo).
  941. X *
  942. X * The find[] struct array holds the field name and length, the index
  943. X * corresponding to the index into the field[] in an Entry.
  944. X *
  945. X * The header and width arrays hold the list format.
  946. X */
  947. X
  948. Xget_extra_ovr(str)
  949. Xchar *str;
  950. X{
  951. X    register int i;
  952. X
  953. X    i = get_extra (str);
  954. X    if (i < 0) {
  955. X    i = add_extra (str);
  956. X    load_changes();
  957. X    }
  958. X    return (i);
  959. X}
  960. X
  961. X
  962. X/*
  963. X * If there's room to add it, append to end.
  964. X * Else Find oldest field which doesn't exist in the setlist and replace it
  965. X *  with the new one.
  966. X */
  967. X
  968. Xadd_extra(str)
  969. Xchar *str;
  970. X{
  971. X    register int i, j, j_age, k;
  972. X
  973. X    for (i = EXSTART; i < MAXTYPE; ++i) {
  974. X    if (Find[i].search == NULL)
  975. X        break;
  976. X    ++Find[i].age;
  977. X    }
  978. X    if (i == MAXTYPE) {                 /* No room to add onto end */
  979. X    j = j_age = -1;
  980. X    for (i = EXSTART; i < MAXTYPE; ++i) {
  981. X        for (k = 0; k < Listsize; ++k) {
  982. X        if (i == header[k])
  983. X            break;
  984. X        }
  985. X        if (k == Listsize  &&  Find[i].age > j_age) {
  986. X        j = i;
  987. X        j_age = Find[i].age;
  988. X        }
  989. X    }
  990. X    i = j;
  991. X    }
  992. X    if (i < 0)
  993. X    return (-1);
  994. X    push_break();
  995. X    if (Find[i].search != NULL)
  996. X    xfree (Find[i].search);
  997. X    Find[i].len = strlen(str);
  998. X    Find[i].search = malloc (Find[i].len + 1);
  999. X    Find[i].notnew = Find[i].age = 0;
  1000. X    strcpy (Find[i].search, str);
  1001. X    changed = 1;
  1002. X    for (j = 0; j < Entries; ++j) {
  1003. X    if (Entry[j].fields[i] && Entry[j].fields[i] != quo_quo)
  1004. X        xfree (Entry[j].fields[i]);
  1005. X    Entry[j].fields[i] = quo_quo;
  1006. X    }
  1007. X    pop_break();
  1008. X    return (i);
  1009. X}
  1010. X
  1011. X
  1012. Xget_extra(str)
  1013. Xchar *str;
  1014. X{
  1015. X    int i;
  1016. X
  1017. X    for (i = 0; Find[i].search; ++i) {
  1018. X    if (strncmp (str, Find[i].search, strlen(str)) == 0) {
  1019. X        Find[i].age = 0;
  1020. X        return (i);
  1021. X    }
  1022. X    }
  1023. X    return (-1);
  1024. X}
  1025. X
  1026. X
  1027. Xm_select(sav, mode)
  1028. Xregister char *sav[];
  1029. X{
  1030. X    char *ptr, *dest;
  1031. X    char l_map[256];
  1032. X    int idx[MAXLIST], ix = 0;
  1033. X    int ok, not, len, scr;
  1034. X    register int i, j, avi;
  1035. X
  1036. X    for (i = 0;i < 256; ++i)
  1037. X    l_map[i] = i;
  1038. X    for (i = 'A'; i <= 'Z'; ++i)
  1039. X    l_map[i] += 'a' - 'A';
  1040. X    hold_load();
  1041. X    i = 0;
  1042. X    idx[ix++] = get_extra_ovr (sav[i++]);
  1043. X    for (; sav[i]; ++i) {
  1044. X    if (strcmp (sav[i], ",") == 0  &&  sav[i + 1])
  1045. X        idx[ix++] = get_extra_ovr (sav[++i]);
  1046. X    }
  1047. X    idx[ix] = -1;
  1048. X    nohold_load();
  1049. X    j = 1;
  1050. X    push_break();
  1051. X    for (i = 0; i < Entries; ++i) {
  1052. X    if (mode == M_CONT  &&  Entry[i].no == 0)
  1053. X        continue;
  1054. X    ix = ok = 0;
  1055. X    avi = 1;
  1056. X    while ((ptr = sav[avi]) != NULL) {
  1057. X        if (ptr[0] == ','  &&  ptr[1] == '\0' && sav[avi+1]) {
  1058. X        ++ix;
  1059. X        avi += 2;
  1060. X        continue;
  1061. X        }
  1062. X        if (not = (*ptr == '!'))
  1063. X        ++ptr;
  1064. X        len = strlen (ptr);
  1065. X        dest = Entry[i].fields[idx[ix]];
  1066. X        if (*ptr == '\0') {
  1067. X        ok = 1;
  1068. X        goto gotit;
  1069. X        }
  1070. X        while (*dest) {
  1071. X        scr = 0;
  1072. X        while (l_map[dest[scr]] == l_map[ptr[scr]] && ptr[scr])
  1073. X            ++scr;
  1074. X        if (ptr[scr] == '\0') {
  1075. X            ok = 1;
  1076. X            goto gotit;
  1077. X        }
  1078. X        ++dest;
  1079. X        }
  1080. X        ++avi;
  1081. X    }
  1082. Xgotit:
  1083. X    Entry[i].no = (ok ^ not) ? j++ : 0;
  1084. X    }
  1085. X    pop_break();
  1086. X    if (Current < 0)
  1087. X    Current = 0;
  1088. X    if (Entries) {
  1089. X    if (Entry[Current].no == 0) {
  1090. X        Current = indexof (1);
  1091. X        if (Current < 0) {
  1092. X         Current = 0;
  1093. X         return (-1);
  1094. X        }
  1095. X    }
  1096. X    } else {
  1097. X    Current = -1;
  1098. X    }
  1099. X    return (1);
  1100. X}
  1101. X
  1102. X
  1103. END_OF_FILE
  1104. if test 13593 -ne `wc -c <'src/dmail/load_mail.c'`; then
  1105.     echo shar: \"'src/dmail/load_mail.c'\" unpacked with wrong size!
  1106. fi
  1107. # end of 'src/dmail/load_mail.c'
  1108. fi
  1109. if test -f 'src/uucico/gio.c' -a "${1}" != "-c" ; then 
  1110.   echo shar: Will not clobber existing file \"'src/uucico/gio.c'\"
  1111. else
  1112. echo shar: Extracting \"'src/uucico/gio.c'\" \(16481 characters\)
  1113. sed "s/^X//" >'src/uucico/gio.c' <<'END_OF_FILE'
  1114. X
  1115. X/*
  1116. X *  GIO.C    WINDOWED G PROTOCOL
  1117. X *
  1118. X *  Rewritten from scratch, except the checksum routine which was
  1119. X *  rewritten but based on the old one.
  1120. X *
  1121. X *  WINDOW SIZE:    When changing the window size be sure there
  1122. X *            are enough buffers available for pending txs.
  1123. X *
  1124. X *  GIO.C (c)Copyright 1989, Matthew Dillon, All Rights Reserved
  1125. X */
  1126. X
  1127. X#include <stdio.h>
  1128. X#include <stdlib.h>
  1129. X#include <exec/types.h>
  1130. X#include <proto/all.h>
  1131. X
  1132. Xvoid    FrameToPacket();
  1133. X
  1134. Xextern int debug;
  1135. Xextern int WindowOne;
  1136. X
  1137. X#define SUCCESS 0
  1138. X#define FAIL    1
  1139. X
  1140. X#define MAGIC        0125252
  1141. X#define DLE        0x10
  1142. X#define WINDOWSIZE  2        /*  WindowSize = 1 or 2  */
  1143. X#define SEGSIZEK    2        /*  64 bytes ??     */
  1144. X
  1145. X#define SUB1(var)   (((var)-1)&7)
  1146. X
  1147. Xtypedef unsigned char    ubyte;
  1148. Xtypedef unsigned short    uword;
  1149. X
  1150. Xtypedef struct {
  1151. X    ubyte   Dle;    /*  Literal ASCII DLE                */
  1152. X    ubyte   K;        /*  data size 2^(K+4) except K=0 means no data  */
  1153. X    ubyte   CL,CH;    /*  MAGIC - chksum(data) ^ C        */
  1154. X    ubyte   C;
  1155. X    ubyte   X;        /*  K ^ C0 ^ C1 ^ C            */
  1156. X} Frame;
  1157. X
  1158. Xtypedef struct {
  1159. X    ubyte   CType;    /*  bits 7-6 of C    */
  1160. X    ubyte   CCmd;    /*  bits 5-3 of C    */
  1161. X    ubyte   CSeq;    /*  bits 2-0 of C    */
  1162. X    ubyte   PLen;    /*  pre-data (2 bytes) for SHORTDATA type */
  1163. X    ubyte   *Data;    /*  implies CType=LONGDATA or SHORTDATA */
  1164. X    uword   DLen;    /*  length of data    */
  1165. X} Packet;
  1166. X
  1167. X#define CT_CONTROL    (0 << 6)
  1168. X#define CT_ALTCHN    (1 << 6)
  1169. X#define CT_LONGDATA    (2 << 6)
  1170. X#define CT_SHORTDATA    (3 << 6)
  1171. X#define CT_MASK     (3 << 6)
  1172. X
  1173. X#define CC_CLOSE    (1 << 3)
  1174. X#define CC_RJ        (2 << 3)
  1175. X#define CC_SRJ        (3 << 3)
  1176. X#define CC_RR        (4 << 3)
  1177. X#define CC_INITC    (5 << 3)
  1178. X#define CC_INITB    (6 << 3)
  1179. X#define CC_INITA    (7 << 3)
  1180. X#define CC_MASK     (7 << 3)
  1181. X
  1182. X#define SEQ_MASK    7
  1183. X
  1184. X#define WAIT_ACK    1
  1185. X#define WAIT_DATA    2
  1186. X#define WAIT_CONTROL    3
  1187. X
  1188. X#define MaxPktSize    4096
  1189. X
  1190. Xchar    RxBuf[MaxPktSize+4];
  1191. Xchar    TxBuf[4][MaxPktSize+4];
  1192. X
  1193. X                /*  TRANSMIT STAGE        */
  1194. Xchar    TxSeq = 0;        /*  Last send packet        */
  1195. Xchar    TxPend= 0;        /*  hasn't been acked yet   */
  1196. Xuword    TxWinSize;        /*  1 or 2            */
  1197. Xuword    TxSegSize;        /*  maximum segment size    */
  1198. Xchar    TxSegK;         /*  K for TxSegSize        */
  1199. XPacket    TxPacket[8];        /*  contents of last packet */
  1200. X
  1201. X                /*  RECEIVE STAGE        */
  1202. Xchar    RxSeq = 1;        /*  Next expected recv pkt  */
  1203. Xchar    RxRdy = 0;        /*  Has come in..        */
  1204. Xchar    RxRetry = 4;
  1205. Xchar    RxNotAcked = 0;     /*  We have yet to ack it   */
  1206. XPacket    RxPacket;        /*  The packet that has come in */
  1207. X
  1208. X/*
  1209. X *  Get Transmit Buffer.  Note that some space to the left is available
  1210. X */
  1211. X
  1212. Xchar *
  1213. XGetTxBuf()
  1214. X{
  1215. X    static int index = 0;
  1216. X
  1217. X    index = (index + 1) & 3;
  1218. X    return(TxBuf[index] + 2);
  1219. X}
  1220. X
  1221. Xint
  1222. Xgwrdata(fi)
  1223. XFILE *fi;
  1224. X{
  1225. X    int bytes;
  1226. X    char *buf = GetTxBuf();
  1227. X
  1228. X    if (debug > 7)
  1229. X    printf("GWRDATA: ");
  1230. X
  1231. X    while ((bytes = fread(buf, 1, TxSegSize, fi)) >= 0) {
  1232. X    if (SendDataPacket(buf, bytes) != SUCCESS) {
  1233. X        if (debug > 7)
  1234. X        printf("GWR Failed\n");
  1235. X        return(FAIL);
  1236. X    }
  1237. X    if (debug > 7)
  1238. X        printf("\nGWROK ");
  1239. X    if (bytes == 0)
  1240. X        break;
  1241. X    buf = GetTxBuf();
  1242. X    }
  1243. X    if (debug > 7)
  1244. X    printf("\nGWFile Last Ack\n");
  1245. X    while (TxPend) {
  1246. X    if (GetData(WAIT_ACK, NULL) == FAIL)
  1247. X        return(FAIL);
  1248. X    }
  1249. X    return (SUCCESS);
  1250. X}
  1251. X
  1252. X/*
  1253. X *  Write message to the other guy.
  1254. X *
  1255. X *  NOTE: LONGDATA packets used exclusively and \0 fill to end.
  1256. X */
  1257. X
  1258. Xint
  1259. Xgwrmsg(str)
  1260. Xchar *str;
  1261. X{
  1262. X    int len = strlen(str) + 1;      /*  type + str + \0  */
  1263. X
  1264. X    if (debug > 8)
  1265. X    printf("GWRMSG: %s\n", str);
  1266. X
  1267. X    while (len > TxSegSize) {
  1268. X    char *buf = GetTxBuf();
  1269. X    movmem(str, buf, TxSegSize);
  1270. X    if (debug > 8)
  1271. X        printf("GWR-SEND %d\n", TxSegSize);
  1272. X    if (SendDataPacket(buf, TxSegSize) != SUCCESS)
  1273. X        return(FAIL);
  1274. X    len -= TxSegSize;
  1275. X    str += TxSegSize;
  1276. X    }
  1277. X
  1278. X    /*
  1279. X     *    Find optimal packet size (remember, we must force LONGDATA
  1280. X     *
  1281. X     *    Apparently packet sizes less than the agreed upon size are
  1282. X     *    not allowed ???
  1283. X     */
  1284. X
  1285. X    {
  1286. X    short siz = TxSegSize;
  1287. X    char *buf = GetTxBuf();
  1288. X#ifdef NOTDEF
  1289. X    short k = TxSegK;
  1290. X
  1291. X    while (k > 1 && (siz >> 1) >= len) {
  1292. X        --k;
  1293. X        siz >>= 1;
  1294. X    }
  1295. X#endif
  1296. X    if (debug > 8)
  1297. X        printf("GWR-FNL %d %d\n", len, siz);
  1298. X
  1299. X    movmem(str, buf, len);
  1300. X    setmem(buf + len, siz - len, 0);
  1301. X    if (SendDataPacket(buf, siz) != SUCCESS) {
  1302. X        if (debug > 8)
  1303. X        printf("GWR-FAIL\n");
  1304. X        return(FAIL);
  1305. X    }
  1306. X    }
  1307. X    if (debug > 8)
  1308. X    printf("GWR Last Ack\n");
  1309. X    while (TxPend) {
  1310. X    if (GetData(WAIT_ACK, NULL) == FAIL)
  1311. X        return(FAIL);
  1312. X    }
  1313. X    return (SUCCESS);
  1314. X}
  1315. X
  1316. Xint
  1317. Xgrddata(fi)
  1318. XFILE *fi;
  1319. X{
  1320. X    int bytes;
  1321. X    char *buf;
  1322. X
  1323. X    if (debug > 7)
  1324. X    printf("GRDDATA\n");
  1325. X    while ((bytes = RecvDataPacket(&buf)) > 0) {
  1326. X    if (debug > 7)
  1327. X        printf("GRDDATA blk %d\n", bytes);
  1328. X    fwrite(buf, 1, bytes, fi);
  1329. X    }
  1330. X    if (debug > 7)
  1331. X    printf("GRDDATA end %d\n", bytes);
  1332. X    if (bytes < 0)
  1333. X    return(FAIL);
  1334. X    else
  1335. X    return(SUCCESS);
  1336. X}
  1337. X
  1338. Xgrdmsg(buf, maxlen)
  1339. Xchar *buf;
  1340. X{
  1341. X    short i;
  1342. X    short n;
  1343. X    short slen;
  1344. X    char *ptr;
  1345. X
  1346. X    i = 0;
  1347. X    if (debug > 8)
  1348. X    printf("GRDMSG\n");
  1349. X    while ((n = RecvDataPacket(&ptr)) > 0) {
  1350. X    ptr[n] = 0;
  1351. X    slen = strlen(ptr);
  1352. X    if (slen > maxlen - 1) {
  1353. X        printf("GRDMSG: Buffer overflow!\n");
  1354. X        return (FAIL);
  1355. X    }
  1356. X    movmem(ptr, buf + i, slen);
  1357. X    buf[i + slen] = 0;
  1358. X    if (slen != n)
  1359. X        break;
  1360. X    i += slen;
  1361. X    maxlen -= slen;
  1362. X    }
  1363. X    if (debug > 8)
  1364. X    printf("GRDMSGEND %d (%d) %s\n", n, i, buf);
  1365. X    if (n < 0) {
  1366. X    buf[0] = 0;
  1367. X    return(FAIL);
  1368. X    }
  1369. X    return(SUCCESS);
  1370. X}
  1371. X
  1372. XSendDataPacket(buf, bytes)
  1373. Xubyte *buf;
  1374. Xint bytes;
  1375. X{
  1376. X    Packet  P;
  1377. X
  1378. X    /*
  1379. X     *    If window exhausted we must wait for at least one ack.
  1380. X     */
  1381. X
  1382. X    if (TxPend == TxWinSize) {
  1383. X    if (GetData(WAIT_ACK, NULL) == FAIL)
  1384. X        return(FAIL);
  1385. X    }
  1386. X
  1387. X    TxSeq = (TxSeq + 1) & 7;        /*  next Tx packet  */
  1388. X
  1389. X    /*
  1390. X     *    Figure out best fit packet size.  Apparently packets smaller
  1391. X     *    then the agreed upon size are not allowed ???
  1392. X     */
  1393. X
  1394. X#ifdef NOTDEF
  1395. X    {
  1396. X    short k = TxSegK;
  1397. X    P.DLen = TxSegSize;
  1398. X    while (k > 1 && P.DLen && (P.DLen >> 1) >= bytes) {
  1399. X        --k;
  1400. X        P.DLen >>= 1;
  1401. X    }
  1402. X    }
  1403. X#else
  1404. X    P.DLen = TxSegSize;
  1405. X#endif
  1406. X
  1407. X    if (bytes < P.DLen) {
  1408. X    uword extra = P.DLen - bytes;
  1409. X    setmem(buf + bytes, extra, 0);
  1410. X    if (extra <= 127) {
  1411. X        P.PLen = 1;
  1412. X        buf[-1] = extra;
  1413. X    } else {
  1414. X        P.PLen = 2;
  1415. X        buf[-2] = 0x80 | extra;
  1416. X        buf[-1] = (extra >> 7);
  1417. X    }
  1418. X    P.CType = CT_SHORTDATA;
  1419. X    } else {
  1420. X    P.PLen = 0;
  1421. X    P.CType = CT_LONGDATA;
  1422. X    }
  1423. X    P.CCmd = TxSeq << 3;    /*  transmit sequence number */
  1424. X    P.CSeq = (RxSeq - 1) & 7;   /*  last valid received pkt  */
  1425. X    P.Data = buf;
  1426. X
  1427. X    if (debug > 8)
  1428. X    printf("WRITE PACKET %d %d\n", TxSeq, P.CSeq);
  1429. X
  1430. X    if (RxNotAcked)             /*  We've acked the rx packet */
  1431. X    RxNotAcked = 0;
  1432. X
  1433. X    TxPacket[TxSeq & 7] = P;
  1434. X    ++TxPend;
  1435. X
  1436. X    WritePacket(&TxPacket[TxSeq & 7], 1);
  1437. X
  1438. X    return(SUCCESS);
  1439. X}
  1440. X
  1441. XRecvDataPacket(pbuf)
  1442. Xchar **pbuf;
  1443. X{
  1444. X    if (RxRdy == 0) {
  1445. X    if (GetData(WAIT_DATA, NULL) != SUCCESS)
  1446. X        return(-1);
  1447. X    }
  1448. X    *pbuf = RxPacket.Data;
  1449. X    RxRdy = 0;
  1450. X    return((int)RxPacket.DLen);
  1451. X}
  1452. X
  1453. Xgturnon(master)
  1454. X{
  1455. X    Packet P;
  1456. X    short retry = 5;
  1457. X    short windowsize = WINDOWSIZE;    /*  our prefered window size */
  1458. X    short segsize = SEGSIZEK;        /*  our prefered segment size */
  1459. X
  1460. X    if (WindowOne)
  1461. X    windowsize = 1;
  1462. X
  1463. X    if (master) {
  1464. X    while (retry > 0) {
  1465. X        WriteCtlPacket(CC_INITA | windowsize);
  1466. X        if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
  1467. X        if (P.CSeq && P.CSeq < windowsize)
  1468. X            windowsize = P.CSeq;
  1469. X        break;
  1470. X        }
  1471. X        --retry;
  1472. X    }
  1473. X    while (retry > 0) {
  1474. X        WriteCtlPacket(CC_INITB | (segsize - 1));
  1475. X        if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
  1476. X        if (P.CSeq < segsize - 1)
  1477. X            segsize = P.CSeq + 1;
  1478. X        break;
  1479. X        }
  1480. X        --retry;
  1481. X    }
  1482. X    while (retry > 0) {
  1483. X        WriteCtlPacket(CC_INITC | windowsize);
  1484. X        if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
  1485. X        if (P.CSeq && P.CSeq < windowsize)
  1486. X            windowsize = P.CSeq;
  1487. X        break;
  1488. X        }
  1489. X        --retry;
  1490. X    }
  1491. X    } else {
  1492. X    while (retry > 0) {
  1493. X        if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
  1494. X        WriteCtlPacket(CC_INITA | windowsize);
  1495. X        if (P.CSeq && windowsize > P.CSeq)
  1496. X            windowsize = P.CSeq;
  1497. X        break;
  1498. X        }
  1499. X        --retry;
  1500. X    }
  1501. X    while (retry > 0) {
  1502. X        if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
  1503. X        WriteCtlPacket(CC_INITB | (segsize - 1));
  1504. X        if (P.CSeq < segsize - 1)
  1505. X            segsize = P.CSeq + 1;
  1506. X        break;
  1507. X        }
  1508. X        --retry;
  1509. X    }
  1510. X    while (retry > 0) {
  1511. X        if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
  1512. X        WriteCtlPacket(CC_INITC | windowsize);
  1513. X        if (P.CSeq && windowsize > P.CSeq)
  1514. X            windowsize = P.CSeq;
  1515. X        break;
  1516. X        }
  1517. X        --retry;
  1518. X    }
  1519. X    }
  1520. X    TxSegK = segsize;
  1521. X    TxSegSize = 1 << (TxSegK + 4);
  1522. X    TxWinSize = windowsize;
  1523. X    if (debug > 0)
  1524. X    printf("Window Size is %d\n", TxWinSize);
  1525. X    if (retry == 0)
  1526. X    return(FAIL);
  1527. X    return(SUCCESS);
  1528. X}
  1529. X
  1530. Xgturnoff()
  1531. X{
  1532. X    Packet P;
  1533. X
  1534. X    WriteCtlPacket(CC_CLOSE);
  1535. X    if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_CLOSE) {
  1536. X    WriteCtlPacket(CC_RR | ((RxSeq - 1) & 7));
  1537. X    return (SUCCESS);
  1538. X    }
  1539. X    return (FAIL);
  1540. X}
  1541. X
  1542. XGetData(waitfor, p)
  1543. XPacket *p;
  1544. X{
  1545. X    Packet P;
  1546. X    short timeout;
  1547. X
  1548. X    /*
  1549. X     *    If we haven't acked the last packet we received we must do
  1550. X     *    so now before we can expect to receive another one!
  1551. X     */
  1552. X
  1553. X    if (waitfor == WAIT_ACK)
  1554. X    timeout = 20;
  1555. X    else if (waitfor == WAIT_DATA)
  1556. X    timeout = 40;
  1557. X    else
  1558. X    timeout = 40;
  1559. X
  1560. X    for (;;) {
  1561. X    if (RxNotAcked) {
  1562. X        WriteCtlPacket(CC_RR | SUB1(RxSeq));
  1563. X        RxNotAcked = 0;
  1564. X    }
  1565. X    if (ReadPacket(&P, timeout) == FAIL) {
  1566. X        if (waitfor == WAIT_DATA) {
  1567. X        if (RxRetry) {
  1568. X            --RxRetry;
  1569. X            if (debug > 8)
  1570. X            printf("\nWAIT-DATA, TIMEOUT, SEND RJ\n");
  1571. X            WriteCtlPacket(CC_RJ | SUB1(RxSeq));
  1572. X            continue;
  1573. X        }
  1574. X        }
  1575. X        if (waitfor == WAIT_ACK) {
  1576. X        if (RxRetry) {
  1577. X            --RxRetry;
  1578. X            if (debug > 8)
  1579. X            printf("\nWAIT-ACK, TIMEOUT, RETRY\n");
  1580. X            WritePacket(&TxPacket[(TxSeq - TxPend + 1) & 7], 1);
  1581. X            continue;
  1582. X        }
  1583. X        }
  1584. X        if (debug > 8)
  1585. X        printf("COMPLETE FAILURE RxRetry = %d\n", RxRetry);
  1586. X        return(FAIL);
  1587. X    }
  1588. X    RxRetry = 4;
  1589. X    switch(P.CType) {
  1590. X    case CT_CONTROL:
  1591. X        switch(P.CCmd) {
  1592. X        case CC_CLOSE:  /*    End of communication ... not an ACK!       */
  1593. X        if (waitfor == WAIT_CONTROL) {
  1594. X            *p = P;
  1595. X            return(SUCCESS);
  1596. X        }
  1597. X        return(FAIL);
  1598. X        case CC_RJ:     /*    Reject packet (P.CSeq == last good packet) */
  1599. X                /*    resend last packet  */
  1600. X
  1601. X        WritePacket(&TxPacket[(P.CSeq + 1) & 7], 1);
  1602. X        {
  1603. X            short i;
  1604. X            for (i = 0; i < TxPend; ++i) {
  1605. X            if (P.CSeq == ((TxSeq - i) & 7))
  1606. X                break;
  1607. X            }
  1608. X            if (i == TxPend)
  1609. X            printf("RJ, bad seq no: %d expected %d-%d\n", P.CSeq, (TxSeq - TxPend + 1) & 7, TxSeq);
  1610. X        }
  1611. X        break;
  1612. X        case CC_SRJ:    /*    Selective Reject (P.CSeq == bad packet # ) */
  1613. X        return(FAIL);
  1614. X        case CC_RR:     /*    Ack to packet  (P.CSeq == packet # acked)   */
  1615. X        if (RecvdAck(P.CSeq) == SUCCESS && waitfor == WAIT_ACK)
  1616. X            return(SUCCESS);
  1617. X        break;
  1618. X        case CC_INITC:
  1619. X        case CC_INITB:
  1620. X        case CC_INITA:
  1621. X        if (waitfor == WAIT_CONTROL) {
  1622. X            *p = P;
  1623. X            return(SUCCESS);
  1624. X        }
  1625. X        return(FAIL);
  1626. X        }
  1627. X        break;
  1628. X    case CT_ALTCHN:
  1629. X        printf("ALTCHN packet ??\n");
  1630. X        break;
  1631. X    case CT_LONGDATA:
  1632. X    case CT_SHORTDATA:
  1633. X        {
  1634. X        char rxseq = P.CCmd >> 3;
  1635. X        char txack = P.CSeq;
  1636. X
  1637. X        if (RxRdy == 1) {
  1638. X            printf("Got two receive packets without me acking!\n");
  1639. X        }
  1640. X        if (rxseq == SUB1(RxSeq)) {
  1641. X            RxNotAcked = 1;
  1642. X            continue;        /*    ignore resent pkts we already have */
  1643. X        } else if (rxseq != RxSeq) {
  1644. X            if (rxseq == ((RxSeq + 1) & 7))     /*  missed one (windowed)   */
  1645. X            WriteCtlPacket(CC_RJ | SUB1(RxSeq));
  1646. X            printf("Received sequence %d, expected %d\n", rxseq, RxSeq);
  1647. X            break;
  1648. X        } else {
  1649. X            if (debug > 6)
  1650. X            printf("RECV SEQUENCE %d\n", rxseq);
  1651. X        }
  1652. X
  1653. X        RecvdAck(txack);
  1654. X
  1655. X        /*
  1656. X         *  Delay sending the ACK back in case we can combine
  1657. X         *  it with the next transmitted packet.
  1658. X         */
  1659. X
  1660. X        RxNotAcked = 1;     /*  we haven't ack'd the rx packet */
  1661. X
  1662. X        RxSeq = (RxSeq + 1) & 7;
  1663. X        RxRdy = 1;
  1664. X        RxPacket = P;
  1665. X        if (waitfor == WAIT_DATA)
  1666. X            return(SUCCESS);
  1667. X        if (TxPend == 0 && waitfor == WAIT_ACK)
  1668. X            return(SUCCESS);
  1669. X        }
  1670. X        break;
  1671. X    }
  1672. X    }
  1673. X}
  1674. X
  1675. XRecvdAck(seq)
  1676. Xchar seq;
  1677. X{
  1678. X    short i;
  1679. X    short seqbase = TxSeq - TxPend + 1;
  1680. X
  1681. X    /*
  1682. X     *  which packet was acked?
  1683. X     */
  1684. X
  1685. X    for (i = 0; i < TxPend; ++i) {
  1686. X    if (seq == ((seqbase + i) & 7))
  1687. X        break;
  1688. X    }
  1689. X    if (i == TxPend) {
  1690. X    if (TxPend)
  1691. X        printf("He acked the wrong packet! %d expected %d\n", seq, TxSeq);
  1692. X    return(FAIL);
  1693. X    }
  1694. X    if (debug > 8)
  1695. X    printf("TxPend %d ->", TxPend);
  1696. X    TxPend = TxPend - i - 1;
  1697. X    if (debug > 8)
  1698. X    printf(" %d\n", TxPend);
  1699. X    return(SUCCESS);
  1700. X}
  1701. X
  1702. XWriteCtlPacket(cc)
  1703. X{
  1704. X    Packet pk;
  1705. X
  1706. X    pk.CType = CT_CONTROL;
  1707. X    pk.CCmd  = cc & CC_MASK;
  1708. X    pk.CSeq  = cc & SEQ_MASK;
  1709. X    pk.PLen  = 0;
  1710. X    pk.DLen  = 0;
  1711. X    WritePacket(&pk, 0);
  1712. X    return(SUCCESS);
  1713. X}
  1714. X
  1715. XWritePacket(pk, async)
  1716. XPacket *pk;
  1717. X{
  1718. X    Frame   F;
  1719. X    uword   sum;
  1720. X
  1721. X    F.Dle = DLE;
  1722. X    F.C   = pk->CType | pk->CCmd | pk->CSeq;
  1723. X    F.K   = 9;
  1724. X
  1725. X    if (pk->CType == CT_SHORTDATA || pk->CType == CT_LONGDATA)
  1726. X    F.K = LenToK(pk->DLen);
  1727. X    else
  1728. X    pk->DLen = 0;
  1729. X
  1730. X    sum = MAGIC - (CheckSum(pk->Data - pk->PLen, pk->DLen) ^ F.C);
  1731. X
  1732. X    F.CH  = sum >> 8;
  1733. X    F.CL  = sum;
  1734. X    F.X   = F.K ^ F.CH ^ F.CL ^ F.C;
  1735. X
  1736. X    if (debug > 8)
  1737. X    printf("WritePacket: F.K = %d F.C = %02x\n", F.K, F.C);
  1738. X
  1739. X    if (async)
  1740. X    xwritea(&F, sizeof(F));
  1741. X    else
  1742. X    xwrite(&F, sizeof(F));      /*  write header    */
  1743. X    if (pk->DLen) {             /*  write data      */
  1744. X    if (async)
  1745. X        xwritea(pk->Data - pk->PLen, pk->DLen);
  1746. X    else
  1747. X        xwrite(pk->Data - pk->PLen, pk->DLen);
  1748. X    }
  1749. X    return(SUCCESS);
  1750. X}
  1751. X
  1752. XReadPacket(pk, timeout)
  1753. XPacket *pk;
  1754. X{
  1755. X    Frame   F;
  1756. X    short   c;
  1757. X    short   i = 0;
  1758. X
  1759. X    pk->Data = RxBuf;
  1760. X    pk->CType = 0xFF;
  1761. X    pk->CCmd  = 0;
  1762. X    pk->CSeq  = 0;
  1763. X
  1764. X    if (debug > 8)
  1765. X    printf("ReadPacket\n");
  1766. X    while ((c = xgetc(timeout)) != EOF) {
  1767. X    if (debug > 8)
  1768. X        printf("RP %d %02x\n", i, c);
  1769. X
  1770. X    switch(i) {
  1771. X    case 0:
  1772. X        if (c == DLE) {
  1773. X        F.Dle = c;
  1774. X        ++i;
  1775. X        }
  1776. X        break;
  1777. X    case 1:
  1778. X        F.K = c;
  1779. X        ++i;
  1780. X        if (c == DLE) { /*  K only valid 0-9    */
  1781. X        F.Dle = c;
  1782. X        i = 1;
  1783. X        }
  1784. X        break;
  1785. X    case 2:
  1786. X        F.CL = c;
  1787. X        ++i;
  1788. X        break;
  1789. X    case 3:
  1790. X        F.CH = c;
  1791. X        ++i;
  1792. X        break;
  1793. X    case 4:
  1794. X        F.C = c;
  1795. X        ++i;
  1796. X        break;
  1797. X    case 5:
  1798. X        F.X = c;
  1799. X        if (F.X != (F.K ^ F.CH ^ F.CL ^ F.C)) {
  1800. X        printf("F.X failed: %02x %02x\n", F.X, (F.K ^ F.CH ^ F.CL ^ F.C));
  1801. X        i = 0;
  1802. X        } else {        /*    get data segment if any */
  1803. X        ++i;
  1804. X        }
  1805. X        break;
  1806. X    }
  1807. X    if (i == 6)
  1808. X        break;
  1809. X    }
  1810. X    if (debug > 8)
  1811. X    printf("RP Hdr i = %d, F.K = %d F.C = %02x\n", i, F.K, F.C);
  1812. X
  1813. X    if (i == 6) {       /*  Receive Data Portion    */
  1814. X    uword pktsize = 1 << (F.K + 4);
  1815. X    uword n;
  1816. X
  1817. X    if (F.K == 0 || F.K == 9)
  1818. X        pktsize = 0;        /*    FIXME is K=0 an illegal case? */
  1819. X
  1820. X    if (pktsize > MaxPktSize) {
  1821. X        printf("Protocol failure pktsize %d/%d/%d\n", pktsize, TxSegSize, MaxPktSize);
  1822. X        return (FAIL);
  1823. X    }
  1824. X    for (n = 0; n < pktsize; ++n) {
  1825. X        if ((c = xgetc(4)) == EOF)
  1826. X        break;
  1827. X        pk->Data[n] = c;
  1828. X    }
  1829. X    if (c != EOF) {
  1830. X        uword hissum;
  1831. X        uword oursum;
  1832. X        hissum = (F.CH << 8) | F.CL;
  1833. X        oursum = MAGIC - (CheckSum(pk->Data, pktsize) ^ F.C);
  1834. X        if (debug > 8)
  1835. X        printf("Got Data, checking: %04x %04x\n", hissum, oursum);
  1836. X        if (hissum == oursum) {
  1837. X        FrameToPacket(&F, pk, pk->Data);
  1838. X        return (SUCCESS);
  1839. X        }
  1840. X    } else {
  1841. X        FrameToPacket(&F, pk, pk->Data);    /* mainly for pk->CType */
  1842. X        return (FAIL);
  1843. X    }
  1844. X    }
  1845. X    /*
  1846. X     *    Timeout, retry?
  1847. X     */
  1848. X    return (FAIL);
  1849. X}
  1850. X
  1851. XCheckSum(s, n)
  1852. Xubyte *s;
  1853. Xint n;
  1854. X{
  1855. X    uword sum;
  1856. X    uword x;
  1857. X    uword t;
  1858. X
  1859. X    if (n == 0)
  1860. X    return(0);
  1861. X    sum = -1;
  1862. X    x = 0;
  1863. X
  1864. X    while (n) {
  1865. X    if (sum & 0x8000)
  1866. X        sum = (sum << 1) | 1;
  1867. X    else
  1868. X        sum = (sum << 1);
  1869. X
  1870. X    t = sum;
  1871. X    sum += *s++;
  1872. X    x += sum ^ n;
  1873. X    if (sum <= t)
  1874. X        sum ^= x;
  1875. X    --n;
  1876. X    }
  1877. X    return((int)sum);
  1878. X}
  1879. X
  1880. Xvoid
  1881. XFrameToPacket(fr, pk, data)
  1882. XFrame *fr;
  1883. XPacket *pk;
  1884. Xubyte *data;
  1885. X{
  1886. X    pk->CType = fr->C & CT_MASK;
  1887. X    pk->CCmd  = fr->C & CC_MASK;
  1888. X    pk->CSeq  = fr->C & SEQ_MASK;
  1889. X    switch(pk->CType) {
  1890. X    case CT_LONGDATA:
  1891. X    pk->DLen = 1 << (fr->K + 4);
  1892. X    break;
  1893. X    case CT_SHORTDATA:
  1894. X    pk->DLen = 1 << (fr->K + 4);
  1895. X    if (pk->Data[0] & 0x80) {
  1896. X        pk->DLen -= (pk->Data[0] & 0x7F) | (pk->Data[1] << 7);
  1897. X        if (pk->DLen < 0) {
  1898. X        printf("DLEN ERROR %d\n", pk->DLen);
  1899. X        pk->DLen = 0;
  1900. X        }
  1901. X        pk->Data += 2;
  1902. X    } else {
  1903. X        pk->DLen -= *pk->Data;
  1904. X        ++pk->Data;
  1905. X    }
  1906. X    break;
  1907. X    default:
  1908. X    pk->DLen = 0;
  1909. X    break;
  1910. X    }
  1911. X}
  1912. X
  1913. XLenToK(bytes)
  1914. Xuword bytes;
  1915. X{
  1916. X    uword n = 32;
  1917. X    uword k = 1;
  1918. X
  1919. X    while (n < bytes) {
  1920. X    n <<= 1;
  1921. X    ++k;
  1922. X    }
  1923. X    if (k > 8) {
  1924. X    printf("Soft error, LenToK: %d %d %d\n", bytes, n, k);
  1925. X    k = 8;
  1926. X    }
  1927. X    return((int)k);
  1928. X}
  1929. X
  1930. END_OF_FILE
  1931. if test 16481 -ne `wc -c <'src/uucico/gio.c'`; then
  1932.     echo shar: \"'src/uucico/gio.c'\" unpacked with wrong size!
  1933. fi
  1934. # end of 'src/uucico/gio.c'
  1935. fi
  1936. echo shar: End of archive 8 \(of 16\).
  1937. cp /dev/null ark8isdone
  1938. MISSING=""
  1939. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
  1940.     if test ! -f ark${I}isdone ; then
  1941.     MISSING="${MISSING} ${I}"
  1942.     fi
  1943. done
  1944. if test "${MISSING}" = "" ; then
  1945.     echo You have unpacked all 16 archives.
  1946.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1947. else
  1948.     echo You still need to unpack the following archives:
  1949.     echo "        " ${MISSING}
  1950. fi
  1951. ##  End of shell archive.
  1952. exit 0
  1953. -- 
  1954. Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to:
  1955.     amiga@cs.odu.edu    
  1956. or    amiga@xanth.cs.odu.edu    ( obsolescent mailers may need this address )
  1957. or    ...!uunet!xanth!amiga    ( very obsolescent mailers need this address )
  1958.  
  1959. Comments, questions, and suggestions should be addressed to ``amiga-request''
  1960. (please only use ``amiga'' for actual submissions) at the above addresses.
  1961.